package org.dolphin.service.base;

import java.lang.reflect.Field;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;

public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

  @Override
  protected CustomAuthentication createSuccessAuthentication(Object principal,
      Authentication authentication, UserDetails user) {
    if (!(user instanceof CustomUserDetails)) {
      throw new IllegalArgumentException("User should be instance of "
          + CustomUserDetails.class.getName());
    }
    CustomUserDetails userDetails = (CustomUserDetails) user;
    CustomAuthenticationToken result = new CustomAuthenticationToken(userDetails.getIdentity(),
        principal, authentication.getCredentials(), userDetails.getLocale(), getAuthoritiesMapper()
            .mapAuthorities(user.getAuthorities()));
    result.setDetails(authentication.getDetails());
    return result;
  }

  protected GrantedAuthoritiesMapper getAuthoritiesMapper() {
    try {
      //TODO if the new version of spring already has getter to access this field, just remove this method
      Field field = getClass().getSuperclass().getSuperclass()
          .getDeclaredField("authoritiesMapper");
      field.setAccessible(true);
      GrantedAuthoritiesMapper authoritiesMapper = (GrantedAuthoritiesMapper) field.get(this);
      return authoritiesMapper;
    } catch (Exception e) {
      throw new RuntimeException("Cannot invoke parent field: " + e.getMessage(), e);
    }
  }
}
